(function($) {

    var RELATIVE_TIME_LIMIT = 1800; // secs (exclusive)

    var useUpdatingTimestamps = true;
    var updatingTimer = null;
    var updatingTimestamps = {}; // id => timestamp map

    function updateTimestamps() {

        var currentDate = new Date();
        for (var id in updatingTimestamps) {
            if (updatingTimestamps.hasOwnProperty(id)) {
                var timestamp = updatingTimestamps[id];
                var secsAgo = Math.round(currentDate.getTime() / 1000 - timestamp);
                if (secsAgo >= RELATIVE_TIME_LIMIT) {
                    delete updatingTimestamps[id];

                    if ($.isEmptyObject(updatingTimestamps)) {
                        clearInterval(updatingTimer);
                        updatingTimer = null;
                    }
                }

                var element = document.getElementById(id);
                if (element) {
                    var minsAgo = Math.round(secsAgo / 60);
                    element.textContent = getRelativeTimestamp(secsAgo, minsAgo, timestamp, currentDate);
                }
            }
        }
    }

    $.timeFormat = function(timestamp) {

        return handleDate(timestamp);
    };

    $.setUseUpdatingTimestamps = function(enable) {

        useUpdatingTimestamps = enable;
    };

    $.updatingTimeFormat = function(timestamp) {

        var currentDate = new Date();
        if (!useUpdatingTimestamps) {
            return getAbsoluteTimestamp(timestamp, currentDate);
        }

        var secsAgo = Math.round(currentDate.getTime() / 1000 - timestamp);
        var minsAgo = Math.round(secsAgo / 60);

        var text = getRelativeTimestamp(secsAgo, minsAgo, timestamp, currentDate);
        if (secsAgo < RELATIVE_TIME_LIMIT) {
            var id = "tf_" + Number.randomId(6);

            updatingTimestamps[id] = timestamp;
            if (updatingTimer === null) {
                updatingTimer = setInterval(updateTimestamps, 30000);
            }

            return "<span id=\"" + id + "\">" + text + "</span>";
        } else {
            return text;
        }
    };

    $.dateFormat = function(day, month, year) {

        if (day === undefined && month === undefined) {
            var currentDate = new Date();
            day = currentDate.getDate();
            month = currentDate.getMonth() + 1;
        }

        var dateString = "";

        if (Modules.currentLocale() == "nl_NL") {
            dateString = day + " " + fullMonths[month - 1];
        } else {
            dateString = fullMonths[month - 1] + " " + day + postfix[day - 1];
        }

        if (year) {
            if (Modules.currentLocale() == "nl_NL") {
                dateString += " " + year;
            } else {
                dateString += ", " + year;
            }
        }

        return dateString;
    };

    $.dayOfWeek = function(day, capitalize) {

        if (day === undefined || day === null) {
            var currentDate = new Date();
            day = currentDate.getDay();
        }

        var dayString = fullDays[day];
        if (capitalize) {
            dayString = dayString.substr(0, 1).toUpperCase() + dayString.substr(1);
        }
        return dayString;
    };

    function handleDate(timestamp) {
        
        if (timestamp) {
            var currentDate = new Date();
            var secsAgo = Math.round(currentDate.getTime() / 1000 - timestamp);
            var minsAgo = Math.round(secsAgo / 60);
            return getRelativeTimestamp(secsAgo, minsAgo, timestamp, currentDate);
        }
        return "";
    }

    function getRelativeTimestamp(secsAgo, minsAgo, timestamp, currentDate) {

        if (secsAgo < 30) {
            return "[[JUST_NOW]]";
        } else if (secsAgo < 90) {
            return "1 [[MINUTE]] [[AGO]]";
        } else if (secsAgo < RELATIVE_TIME_LIMIT) {
            return minsAgo + " [[MINUTES]] [[AGO]]";
        } else {
            return getAbsoluteTimestamp(timestamp, currentDate);
        }
    }

    function getAbsoluteTimestamp(timestamp, currentDate) {

        var date = new Date(parseInt(timestamp) * 1000);

        var timeString = "";
        var dateString = "";

        var minutes = date.getMinutes();
        if (minutes < 10) {
            minutes = "0" + minutes;
        }
        if (Modules.currentLocale() == "nl_NL") {
            timeString = date.getHours() + ":" + minutes;
        } else {
            var hours = date.getHours() % 12;
            if (hours == 0) {
                hours = 12;
            }
            timeString = hours + ":" + minutes + " " + (date.getHours() / 12 >= 1.0 ? "PM" : "AM");
        }

        if (date.getDate() != currentDate.getDate() ||
            date.getMonth() != currentDate.getMonth() ||
            date.getFullYear() != currentDate.getFullYear()) {

            var yesterDate = new Date(currentDate.getTime() - (24 * 60 * 60 * 1000));

            if (date.getDate() == yesterDate.getDate() &&
                date.getMonth() == yesterDate.getMonth() &&
                date.getFullYear() == yesterDate.getFullYear()) {
                dateString = "[[YESTERDAY]]";
            } else {
                if (Modules.currentLocale() == "nl_NL") {
                    dateString = date.getDate() + " " + months[date.getMonth()];
                } else {
                    var day = date.getDate();
                    dateString = months[date.getMonth()] + " " + day + postfix[day - 1];
                }

                if (currentDate - timestamp > 365 * 24 * 60 * 60 * 1000) {
                    if (Modules.currentLocale() == "nl_NL") {
                        dateString += " " + date.getFullYear();
                    } else {
                        dateString += ", " + date.getFullYear();
                    }
                }
            }
        }

        if (dateString == "") {
            return timeString;
        } else {
            if (Modules.currentLocale() == "nl_NL") {
                return dateString + ", " + timeString;
            } else {
                return timeString + " " + dateString;
            }
        }
    }

    var months = [
        "[[MONTH_JAN]]",
        "[[MONTH_FEB]]",
        "[[MONTH_MAR]]",
        "[[MONTH_APR]]",
        "[[MONTH_MAY]]",
        "[[MONTH_JUN]]",
        "[[MONTH_JUL]]",
        "[[MONTH_AUG]]",
        "[[MONTH_SEP]]",
        "[[MONTH_OCT]]",
        "[[MONTH_NOV]]",
        "[[MONTH_DEC]]"
    ];

    var fullMonths = [
        "[[MONTH_JANUARY]]",
        "[[MONTH_FEBRUARY]]",
        "[[MONTH_MARCH]]",
        "[[MONTH_APRIL]]",
        "[[MONTH_MAY]]",
        "[[MONTH_JUNE]]",
        "[[MONTH_JULY]]",
        "[[MONTH_AUGUST]]",
        "[[MONTH_SEPTEMBER]]",
        "[[MONTH_OCTOBER]]",
        "[[MONTH_NOVEMBER]]",
        "[[MONTH_DECEMBER]]"
    ];

    var fullDays = [
        "[[DAY_SUNDAY]]",
        "[[DAY_MONDAY]]",
        "[[DAY_TUESDAY]]",
        "[[DAY_WEDNESDAY]]",
        "[[DAY_THURSDAY]]",
        "[[DAY_FRIDAY]]",
        "[[DAY_SHABBAS]]"
    ];

    var postfix = [
        "st", "nd", "rd", "th", "th", "th", "th", "th", "th", "th",
        "th", "th", "th", "th", "th", "th", "th", "th", "th", "th",
        "st", "nd", "rd", "th", "th", "th", "th", "th", "th", "th",
        "st"
    ];

})(jQuery);
